package jamun

object Dependency {
  val pattern = java.util.regex.Pattern.compile("[()]")
  private def trim(name:String) = pattern.split(name, 2) (0)

/*
  lazy val whoProvides = {
    val map = new MultiMap[String, MngdPackage]
    ManagedPkgs.list foreach {p => 
      p.provides foreach {re => 
        map add (trim(re.name), p)
      }
    }
    map
  }

  class MultiMap[Key,Value] extends collection.mutable.HashMap[Key,List[Value]] {
    override def default(k:Key):List[Value] = Nil
    def add(k:Key, v:Value) = {
      val prev = apply(k)
      if (!(prev contains v))
        update(k, v :: apply(k))
    }
  }
*/

  private def whoProvides(requirement:String) = {
    ManagedPkgs.getProviders(requirement)
  }

  def getFor(pkgs:Seq[MngdPackage]) = {
    val jobQ = new scala.collection.mutable.Queue[MngdPackage]
    var deps:List[String] = Nil
    def shouldConsider(name:String, reject:List[String]) = {
      (!(reject contains name)) &&
      (!(InstalledPkgs.map isDefinedAt (name))) &&
      (!(jobQ map (_.name) contains (name)))
    }

    var processed = scala.collection.mutable.HashSet.empty[String]

    jobQ ++= pkgs filter (p => !(InstalledPkgs.map isDefinedAt p.name))

    while (jobQ.length > 0) {
      val pkg = (jobQ dequeue)
      deps ::= pkg.name
      println ("looking at: " + pkg.name)
      ManagedPkgs.getRequirements(pkg.name) foreach {r => 
        // val baseName = trim(r.name)
        val baseName = trim(r)
        if (!(processed contains baseName)) {
          val whoProvided = whoProvides(baseName)
          if (whoProvided.length != 0) {
            val accepted = (whoProvided filter (w => shouldConsider(w.name, deps)))
            if (accepted.length > 0) {
              val chosenPkg = accepted(0)
              if (accepted.length > 1) {
                println("warning: multiple pkgs provide [" + baseName + "]. Choosing the first one.")
              }
              println("accepted: " + chosenPkg.name + " " + chosenPkg.version)
              jobQ += chosenPkg
            }
          } else println("!!!!!!! Not found: " + baseName)

          processed += baseName
        }
      }
    }

    println ("processed: " + processed.size)

    deps
  }

}
